/*
*	This is the controller which give controll signal according to Op and Func
*
*
*
*/

module Controller(
	Op,
	Funct,
	RegWrite,
	MemtoReg,
	MemWrite,
	ALUControl,
	ALUSrc,
	ExtOp,
	RegDst,
	Branch,
	BrEq,
	Jump,
	JumpRun,
	JumpReg
);
	input[5:0] Op;
	input[5:0] Funct;
	
	output RegWrite,MemtoReg,MemWrite,RegDst,Branch,BrEq;
	output Jump,JumpRun,JumpReg;
	output[2:0] ALUControl;
	output[1:0] ALUSrc,ExtOp;
	
	reg RegWrite,MemtoReg,MemWrite,RegDst,Branch,BrEq;
	reg Jump,JumpRun,JumpReg;
	reg[2:0] ALUControl;
	reg[1:0] ALUSrc,ExtOp;
	initial begin
		RegWrite = 0;
		MemtoReg = 0;
		MemWrite = 0;
		RegDst	 = 0;
		Branch	 = 0;
		ALUControl = 0;
		ALUSrc 	 = 0;
		ExtOp    = 0;
		BrEq	 = 0;
		Jump	 = 0;
		JumpRun	 = 0;
		JumpReg	 = 0;
	end
	
	always @(Op,Funct) begin
		RegWrite = 0;
		MemtoReg = 0;
		MemWrite = 0;
		RegDst	 = 0;
		Branch	 = 0;
		ALUControl = 0;
		ALUSrc 	 = 0;
		ExtOp    = 0;
		BrEq	 = 0;
		Jump	 = 0;
		JumpRun	 = 0;
		JumpReg	 = 0;
		case(Op)
			6'b000000:
				case(Funct)
					6'b100000: // for add
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUSrc = 2'b00;
						ALUControl = 3'b010;
					end
					// 6'b100001: for addu
						
					6'b100100: // for and
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUSrc = 2'b00;
						ALUControl = 3'b000;
					end
					6'b001000: // for jr
					begin
						RegWrite = 1;
						RegDst = 1;
						JumpRun = 0;
						Jump = 1;
						JumpReg = 1;
					end
					6'b100111: // for nor
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUControl = 3'b100;
						ALUSrc = 2'b00;
					end
					6'b100101: //for or
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUControl = 3'b001;
						ALUSrc = 2'b00;
					end
					6'b101010: // for slt
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUControl = 3'b111;
						ALUSrc = 2'b00;
					end
					6'b000000: // for sll
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUControl = 3'b101;
						ALUSrc = 2'b01;
					end
					6'b000010: // for srl
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUControl = 3'b110;
						ALUSrc = 2'b01;
					end
					6'b100010: // for sub
					begin
						RegWrite = 1;
						RegDst = 1;
						ALUControl = 3'b011;
						ALUSrc = 2'b00;
					end
				endcase
			6'h8: // for addi
			begin
				RegWrite = 1;
				RegDst = 0;
				ALUControl = 3'b010;
				ALUSrc = 2'b10;
				ExtOp = 2'b01;
			end
			// 6'b001001: for addiu
				
			6'b001100: // for andi
			begin
				RegWrite = 1;
				RegDst = 0;
				ALUControl = 3'b000;
				ALUSrc = 2'b10;
				ExtOp = 2'b00;
			end
			6'h4: // for beq
			begin
				Branch = 1;
				ExtOp = 2'b01;
				BrEq = 1;
			end
			6'h5: //for bne
			begin
				Branch = 1;
				ExtOp = 2'b01;
				BrEq = 0;
			end
			6'b000010: // for j
			begin
				Jump = 1;
				JumpReg = 0;
				JumpRun = 0;			
			end
			6'b000011: // for jal
			begin
				Jump = 1;
				JumpReg = 0;
				JumpRun = 1;
			end
			6'b001111: // for lui
			begin
				RegWrite = 1;
				RegDst = 0;
				ALUControl = 3'b010; // suppose that r[0] = 0;
				ALUSrc = 2'b10;
				ExtOp = 2'b10;
			end
			6'b001101: // for ori
			begin
				RegWrite = 1;
				RegDst = 0;
				ALUControl = 3'b001;
				ALUSrc = 2'b10;
				ExtOp = 2'b00;
			end
			6'b001010: // slti
			begin
				RegWrite = 1;
				RegDst = 0;
				ALUControl = 3'b111;
				ALUSrc = 2'b10;
				ExtOp = 2'b01;
			end
			6'h2b: // for sw
			begin			
				MemWrite = 1;
				RegDst = 0;
				ALUControl = 3'b010;
				ALUSrc = 2'b10;
				ExtOp = 2'b01;
			end
			6'h23: // for lw
				begin
					RegWrite = 1;
					MemtoReg = 1;
					RegDst = 0;
					ALUSrc = 2'b10;
					ALUControl = 3'b010;
					ExtOp = 2'b01;
				end
		endcase
	end


endmodule
